Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

53장. API Gateway의 인증 — IAM · Cognito · Lambda Authorizer

이 장에서 말하고자 하는 것

API Gateway의 진가는 인증이다.

ALB에 인증을 박는 것보다 API Gateway에서 처리하면

  • 애플리케이션이 가벼워지고
  • 인증 정책을 한 곳에서 관리할 수 있고
  • 미인증 요청이 ECS까지 도달하지 않는다

이 장은 API Gateway가 제공하는 세 가지 인증 방식을 본다.


1. 세 가지 방식

방식누가 검증하나용도
IAMAWS SigV4 서명내부 호출 / 머신 간
Cognito / JWT AuthorizerJWT 토큰사용자 인증
Lambda Authorizer커스텀 Lambda자유 로직

2. IAM 인증 — 내부 호출

요청에 AWS SigV4 서명 부착
  ↓
API Gateway가 IAM 정책으로 검증
  ↓
허용 → ECS / 거부 → 403

용도:

  • 서비스 → 서비스
  • Lambda → API
  • CI → API

사용자에게는 거의 쓰지 않는다 (서명 만들기 부담).


3. JWT Authorizer — 사용자 인증의 표준

사용자 → API에 Bearer 토큰
  ↓
API Gateway가 JWT 서명 · 만료 · scope 검증
  ↓
검증 통과 → 백엔드로 패스 (사용자 정보를 헤더에 주입)
검증 실패 → 401

토큰 발급자는 보통 둘 중 하나다.

  • Amazon Cognito
  • 외부 IdP — Auth0, Okta, Firebase, Google

4. Cognito User Pool

Cognito는 두 가지로 나뉜다.

  • User Pool — 회원가입 / 로그인 / 비밀번호 / MFA
  • Identity Pool — AWS 임시 자격증명 발급

대부분의 경우 User Pool만 쓴다.

회원가입 / 로그인 → User Pool
  ↓ JWT 토큰
사용자 → API Gateway → 백엔드

5. Lambda Authorizer — 자유 로직

JWT 표준 검증으로 부족할 때 쓴다.

  • 토큰을 외부 IdP에 매번 introspection
  • 사용자별 권한을 DB에서 조회
  • 회사 내부 토큰 포맷

Lambda 함수가

입력: 요청의 토큰
출력: ALLOW / DENY + 컨텍스트

를 돌려준다.

단순 JWT는 JWT Authorizer로
복잡한 로직은 Lambda Authorizer로


6. 인증 캐시

Lambda Authorizer는 매 요청마다 부르면 비싸다.

응답 캐시 TTL: 300초

같은 토큰이면 5분간 결과 재사용.

토큰 만료까지 남은 시간 > 캐시 TTL
안 그러면 만료된 토큰이 캐시 동안 통과한다


7. 우리 서비스에서

[사용자]
  ↓ Bearer <JWT>
[API Gateway]
  ├─ JWT Authorizer (Cognito User Pool)
  │    ↓ ALLOW
  └─ VPC Link
        ↓
   [Private ALB]
  • 사용자 인증: Cognito + JWT Authorizer
  • 내부 머신 호출: IAM
  • 특수 검증: Lambda Authorizer

8. 직접 확인해보기 — CLI

aws apigatewayv2 create-authorizer \
  --api-id <api-id> \
  --authorizer-type JWT \
  --identity-source '$request.header.Authorization' \
  --jwt-configuration Audience=<client-id>,Issuer=https://cognito-idp.ap-northeast-2.amazonaws.com/<userpool-id> \
  --name cognito-jwt

aws apigatewayv2 update-route \
  --api-id <api-id> \
  --route-id <route-id> \
  --authorization-type JWT \
  --authorizer-id <authorizer-id>

9. 코드로는 이렇게 생겼다 — Terraform

resource "aws_cognito_user_pool" "main" {
  name = "msa-users"
}

resource "aws_cognito_user_pool_client" "web" {
  name            = "web"
  user_pool_id    = aws_cognito_user_pool.main.id
  generate_secret = false
}

resource "aws_apigatewayv2_authorizer" "jwt" {
  api_id           = aws_apigatewayv2_api.main.id
  authorizer_type  = "JWT"
  identity_sources = ["$request.header.Authorization"]
  name             = "cognito"

  jwt_configuration {
    audience = [aws_cognito_user_pool_client.web.id]
    issuer   = "https://cognito-idp.ap-northeast-2.amazonaws.com/${aws_cognito_user_pool.main.id}"
  }
}

resource "aws_apigatewayv2_route" "orders" {
  api_id             = aws_apigatewayv2_api.main.id
  route_key          = "ANY /api/orders/{proxy+}"
  target             = "integrations/${aws_apigatewayv2_integration.alb.id}"
  authorization_type = "JWT"
  authorizer_id      = aws_apigatewayv2_authorizer.jwt.id
}

이 한 묶음이 “토큰이 있어야만 들어올 수 있는 API” 다.


10. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. ALB · 백엔드에서 같은 인증을 또 한다

이중 검증으로 운영이 어려워진다.

인증은 한 곳에서, 그 뒤로는 신뢰

안티패턴 2. Bearer 만 보고 통과시킨다

서명 · 만료 · issuer · audience 모두 검증해야 한다.
JWT Authorizer는 자동 처리한다.

안티패턴 3. Lambda Authorizer 캐시 TTL을 길게 둔다

만료된 토큰이 캐시 동안 통과될 수 있다.

안티패턴 4. 비공개 엔드포인트에 Authorizer를 안 붙인다

모든 route에 명시적인 authorization_type을 설정한다.


11. 한 줄로 정리

API Gateway의 인증은 IAM · JWT · Lambda Authorizer 셋이며,
JWT + Cognito 조합이 일반 사용자 인증의 표준이다


12. 이 장의 핵심 정리

  1. API Gateway는 IAM · JWT · Lambda Authorizer 세 가지 인증을 제공한다.
  2. 사용자 인증의 표준은 JWT + Cognito 또는 외부 IdP다.
  3. Lambda Authorizer는 자유로운 로직이 필요할 때 쓴다.
  4. 인증은 한 곳에서, 백엔드는 신뢰한다.
  5. 캐시 TTL은 토큰 만료보다 짧게 둔다.